package cn.com.cmbc.utils;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.stream.Stream;

public class FileUtil {
    private static final Logger LOG = LoggerFactory.getLogger(FileUtil.class);

    public static final String DEFAULT_PATH = "E:\\BaiduNetdiskDownload";

    /**
     * 将文件名编码为固定长度的字符串
     * 此方法使用MD5哈希算法对文件名进行编码，并根据指定长度进行格式化或截断
     *
     * @param fileName 待编码的文件名
     * @param len 编码后字符串的目标长度
     * @return 根据目标长度格式化或截断后的编码字符串
     * @throws RuntimeException 如果系统不支持MD5算法，则抛出运行时异常
     */
    public static String encodeFileName(String fileName, int len) {
        try {
            // 使用 MD5 哈希算法
            MessageDigest digest = MessageDigest.getInstance("MD5");
            byte[] hashBytes = digest.digest(fileName.getBytes());
            String hexString = toHexString(hashBytes);

            // 如果字符串长度小于指定长度，使用格式化操作将其填充到指定长度
            if (hexString.length() < len) {
                return String.format("%0" + len + "d", Long.parseLong(hexString));
            } else if (hexString.length() > len) {
                // 如果字符串长度大于指定长度，截断字符串到指定长度
                return hexString.substring(0, len);
            } else {
                // 如果字符串长度等于指定长度，直接返回该字符串
                return hexString;
            }
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5 algorithm not found", e);
        }
    }

    public static String encodeFileSize(long size, int len) {
        String strSize = String.valueOf(size);
        if (strSize.length() < len) {
            return String.format("%0" + len + "d", Long.parseLong(strSize));
        }else if (strSize.length() > len) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < len; i++) {
                sb.append('9');
            }
            // 返回构建好的字符串
            return sb.toString();
        }else {
            return strSize;
        }
    }


    /**
     * 将字节数组转换为十六进制字符串
     * 此方法用于将给定的字节数组转换成一个十六进制表示的字符串，常用于数据的可视化表示或存储
     *
     * @param bytes 待转换的字节数组，不能为空
     * @return 返回表示原始字节数组的十六进制字符串
     */
    public static String toHexString(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            // 将字节转换为无符号整数并进一步转换为十六进制字符串
            String hex = Integer.toHexString(0xff & b);
            // 如果转换后的十六进制字符串长度为1，则在前面补0，保证每个字节的十六进制表示长度为2
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    public static String getFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf(".");
        if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
            return fileName.substring(dotIndex + 1).toLowerCase();
        } else {
            return "";
        }
    }

    public static long getDirectorySize(Path directory) throws IOException {
        try (Stream<Path> stream = Files.walk(directory)) {
            return stream.filter(Files::isRegularFile)
                    .mapToLong(file -> {
                        try {
                            return Files.size(file);
                        } catch (IOException e) {
                            LOG.error("Error getting file size for {}: {}", file, e.getMessage(), e);
                            return 0L;
                        }
                    })
                    .sum();
        }
    }


    public static void main(String[] args) {

    }
}
